package il.ac.braude.sona.gui.forms;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.image.ImageObserver;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JPanel;
/**
 * Class ImagePanel represents a panel with a background image
 * @author  Ofek Ron
 * @author Avihay Avitan
 * @author Nitzan Inbar
 * @author Sasha Rozenthal
 */
public class ImagePanel extends JPanel {
	/**
	 * image to be used
	 */
	private Image mBackground;
	/**
	 * image hight
	 */
	private int mh;
	/**
	 * image width
	 */
	private int mw;
	
	private static ExecutorService es = Executors.newSingleThreadExecutor();
	
	private AtomicBoolean valueIsAdjusting = new AtomicBoolean(false);
	/**
	 * initialize anew image panel
	 */
	public ImagePanel() {
		init();
	}
	/**
	 * Initialize a new image panel with a given image
	 * @param image
	 */
	public ImagePanel(Image image) {
		setBackground(image);
		init();
	}
	/**
	 * initialize anew image panel with a given image
	 * with a boolean value for changing image size
	 * @param image - a given image
	 * @param b - boolean value that determines the size of the image
	 */
	public ImagePanel(Image image, boolean b) {
		setBackground(image,b);
		init();
	}
	/**
	 * initialize image panel with the given layout manager
	 * @param manager - layout manager
	 */
	public ImagePanel(LayoutManager manager) {
		super(manager);
		init();
	}
	/**
	 * sets the component opaque
	 */
	public void init() {
		setOpaque(false);
	}
	@Override
	public void setPreferredSize(Dimension preferredSize) {
		if (mBackground != null && preferredSize.height*preferredSize.width!=0 && !valueIsAdjusting.get()) 
			mBackground=mBackground.getScaledInstance(preferredSize.width, preferredSize.height, Image.SCALE_SMOOTH);
		super.setPreferredSize(preferredSize);
	}
	@Override
	public void paint(Graphics g) {
		if (mBackground!=null) {
			Graphics2D g2d = (Graphics2D)g.create();
			g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
			g2d.drawImage(mBackground, 0, 0, getWidth(),getHeight(),this);
		}
		super.paint(g);
	}
	
	@Override
	public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
		if ((infoflags&ImageObserver.HEIGHT)>0) 
			mh=h;
		else if ((infoflags&ImageObserver.WIDTH)>0)
			mw=w;
		if (mw!=-1 && mh!=-1) setPreferredSize(new Dimension(mw,mh));
		return super.imageUpdate(img, infoflags, x, y, w, h);
	}
	/**
	 * sets the background image
	 * @param image - a given image to set background with
	 */
	
	public void setBackground(Image image) {
		mBackground = image;
		if (image == null) {
			setPreferredSize(null);
			return;
		}
		mBackground.setAccelerationPriority(1);
	}
	/**
	 * set background with a given image and 
	 * change size determined by boolean value
	 * @param image - the image to be set
	 * @param shouldChangeSize - boolean value for size changing 
	 */
	
	public void setBackground(Image image, boolean shouldChangeSize) {
		mBackground = image;
		if (image == null) {
			setPreferredSize(null);
			return;
		}
		mBackground.setAccelerationPriority(1);
		mh = image.getHeight(this);
		mw = image.getWidth(this);
		if (mw==-1 || mh==-1) return;
		if (shouldChangeSize) setPreferredSize(new Dimension(mw,mh));
	}

	/**
	 * @return mBackground - the background image
	 */	
	public Image getImage() {
		return mBackground;
	}
}
